package bll

import (
	"context"
	"encoding/json"
	"github.com/hashicorp/golang-lru/v2/expirable"
	"ota/model"
	"time"
)

var (
	userUpgradeStatusCache = expirable.NewLRU[int64, any](12800, nil, time.Hour)
	upgradePlanCache       = expirable.NewLRU[int64, any](12800, nil, time.Hour*24*30)
	upgradeStrategyCache   = expirable.NewLRU[int64, any](12800, nil, time.Hour*24*30)
	userUpgradeCache       = expirable.NewLRU[int64, any](12800, nil, time.Hour)
)

type userUpgradeValueCache struct {
	ID                      int64           `json:"id" gorm:"column:id"`
	UpgradeType             int             `json:"upgrade_type" gorm:"column:upgrade_type"`
	EbikeSnCode             string          `json:"ebike_sn_code" gorm:"column:ebike_sn_code"`
	UserUpgradeStatus       int             `json:"user_upgrade_status" gorm:"column:user_upgrade_status"`
	UserUpgradeStatusDetail json.RawMessage `json:"user_upgrade_status_detail" gorm:"column:user_upgrade_status_detail"`
	UpgradePlanStatus       int             `json:"upgrade_plan_status" gorm:"column:upgrade_plan_status"`
	PlanId                  int64           `json:"plan_id" gorm:"column:plan_id"`
	StrategyId              int64           `json:"strategy_id" gorm:"column:strategy_id"`
	Order                   json.RawMessage `json:"order" gorm:"column:order"`
	UpgradePlanDetail       json.RawMessage `json:"upgrade_plan_detail" gorm:"column:upgrade_plan_detail"`
}

func getUserUpgradeCache(ctx context.Context, in *model.OtaUpgradeRequest) (*userUpgradeValueCache, error) {

	var (
		err                 error
		respUserUpgrade     *model.UserUpgradeInfo
		respUpgradePlan     *model.UpgradePlanInfo
		respUpgradeStrategy *model.UpgradeStrategyInfo
	)

	if v, ok := userUpgradeCache.Get(in.ID); !ok {
		respUserUpgrade, err = UserUpgrade.Find(ctx, &model.UserUpgradeInfoRequest{Id: in.ID})
		if err != nil {
			return nil, err
		}
		userUpgradeCache.Add(in.ID, respUserUpgrade)
		in.PlanId = respUserUpgrade.PlanId
		in.StrategyId = respUserUpgrade.UpgradeStrategyID
	} else {
		respUserUpgrade = v.(*model.UserUpgradeInfo)
	}

	if v, ok := upgradePlanCache.Get(in.ID); !ok {
		respUpgradePlan, err = UpgradePlan.Find(ctx, &model.UpgradePlanInfoRequest{Id: in.PlanId})
		if err != nil {
			return nil, err
		}
		upgradePlanCache.Add(in.ID, respUpgradePlan)
	} else {
		respUpgradePlan = v.(*model.UpgradePlanInfo)
	}

	if v, ok := upgradeStrategyCache.Get(in.ID); !ok {
		respUpgradeStrategy, err = UpgradeStrategy.Find(ctx, &model.UpgradeStrategyInfoRequest{Id: in.StrategyId})
		if err != nil {
			return nil, err
		}
		upgradeStrategyCache.Add(in.ID, respUpgradeStrategy)
	} else {
		respUpgradeStrategy = v.(*model.UpgradeStrategyInfo)
	}

	resp := &userUpgradeValueCache{
		ID:                      in.ID,
		UpgradeType:             respUpgradeStrategy.UpgradeType,
		EbikeSnCode:             respUserUpgrade.EbikeSnCode,
		UserUpgradeStatus:       respUserUpgrade.Status,
		UserUpgradeStatusDetail: respUserUpgrade.StatusDetail,
		UpgradePlanStatus:       respUpgradePlan.Status,
		PlanId:                  respUserUpgrade.PlanId,
		StrategyId:              respUserUpgrade.UpgradeStrategyID,
		Order:                   respUpgradeStrategy.Order,
		UpgradePlanDetail:       respUpgradePlan.Detail,
	}
	return resp, nil
}
